#include "../Base.h"

PKDPC dpc;
PKTIMER timer;
VOID
DefaultDpcFunc(
	_In_ struct _KDPC* Dpc,
	_In_opt_ PVOID DeferredContext,
	_In_opt_ PVOID SystemArgument1,
	_In_opt_ PVOID SystemArgument2
) {
	LOG("Default dpc routine   processor = %d;irql = %d;", KeGetCurrentProcessorNumber(), KeGetCurrentIrql());
	if (dpc) {
		ExFreePoolWithTag(Dpc, 'yang');
	}
	if (timer) {
		KeCancelTimer(timer);
		ExFreePoolWithTag(timer, 'yang');
	}
}

VOID InsertInstantDpc() {
	dpc = (PKDPC)ExAllocatePoolWithTag(NonPagedPool, sizeof(KDPC), 'yang');
	KeInitializeDpc(dpc, DefaultDpcFunc, NULL);
	KeInsertQueueDpc(dpc, NULL, NULL);
}

VOID InsertDelayDpc() {
	dpc = (PKDPC)ExAllocatePoolWithTag(NonPagedPool, sizeof(KDPC), 'yang');
	timer = (PKTIMER)ExAllocatePoolWithTag(NonPagedPool, sizeof(KTIMER), 'yang');
	KeInitializeDpc(dpc, DefaultDpcFunc, NULL);
	KeInitializeTimer(timer);
	LARGE_INTEGER time;
	time.QuadPart = -10000 * 1000;
	KeSetTimer(timer, time, dpc);
}

NTSTATUS InsertProcessorDpc(long processorNumber) {
	dpc = (PKDPC)ExAllocatePoolWithTag(NonPagedPool, sizeof(KDPC), 'yang');
	KeInitializeDpc(dpc, DefaultDpcFunc, NULL);
	KeSetTargetProcessorDpc(dpc, processorNumber);
	KeInsertQueueDpc(dpc, NULL, NULL);
	return STATUS_SUCCESS;
}